package com.ys.service.flow.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.ys.entity.sys.YsProcInstOther;
import com.ys.mapper.sys.YsProcInstOtherMapper;
import com.ys.util.CheckUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ys.entity.flow.YspDef;
import com.ys.entity.flow.YspDefLink;
import com.ys.entity.flow.YspDefNode;
import com.ys.entity.flow.YspDeploy;
import com.ys.entity.flow.YspModel;
import com.ys.entity.flow.YspTask;
import com.ys.entity.flow.YspTaskAudit;
import com.ys.entity.flow.YspTaskAuditUser;
import com.ys.entity.flow.YspTaskFlowPath;
import com.ys.entity.sys.TsUserInfo;
import com.ys.entity.sys.YsProcInst;
import com.ys.entity.sys.YsRole;
import com.ys.enume.flow.YsProcInstEnum;
import com.ys.enume.flow.YspDefNodeEnum;
import com.ys.enume.flow.YspTaskAuditEnum;
import com.ys.enume.flow.YspTaskAuditUserEnum;
import com.ys.enume.flow.YspTaskFlowPathEnum;
import com.ys.mapper.flow.FlowMapper;
import com.ys.mapper.flow.YspTaskAuditMapper;
import com.ys.mapper.flow.YspTaskAuditUserMapper;
import com.ys.mapper.flow.YspTaskFlowPathMapper;
import com.ys.mapper.flow.YspTaskMapper;
import com.ys.mapper.sys.YsProcInstMapper;
import com.ys.service.flow.YspTaskService;
import com.ys.vo.Flow;
import com.ys.vo.R;

@Service("yspTaskService")
public class YspTaskServiceImpl implements YspTaskService {
	
    private static final Logger logger = LoggerFactory.getLogger(YspTaskServiceImpl.class);

	@Autowired
	private FlowMapper flowMapper;
	@Autowired
	private YspTaskMapper yspTaskMapper;
	@Autowired
	private YspTaskAuditMapper yspTaskAuditMapper;
	@Autowired
	private YspTaskAuditUserMapper yspTaskAuditUserMapper;
	@Autowired
	private YspTaskFlowPathMapper yspTaskFlowPathMapper;
	
	@Autowired
	private YsProcInstMapper ysProcInstMapper;

	@Autowired
	private CheckUtil checkUtil;

	@Autowired
	private YsProcInstOtherMapper ysProcInstOtherMapper;


	
	@Override
	public R init(String codeModel, String bid, String createUserId) throws Exception {
		
		// 确定模型
		if (codeModel == null || codeModel.length() == 0) {
			return R.error("模型编码不能为空");
		}
		YspModel yspModel = new YspModel().setCode(codeModel).queryFirst();
		if (yspModel == null) {
			return R.error("模型不存在");
		}
		
		// 确定流程部署版本
		YspDeploy yspDeploy = new YspDeploy().setModelId(yspModel.getId()).setVersion(yspModel.getVersionLatest()).queryFirst();
		
		// 确定流程定义
		YspDef yspDef = new YspDef().setDeployId(yspDeploy.getId()).queryFirst();
		
		// 添加任务
		YspTask yspTask = null;
		{
			Long defId = yspDef.getId();
			String name = yspDef.getName();
			yspTask = YspTask.yspTask(defId, name, 1);
			yspTaskMapper.insert(yspTask);
		}
		
		// 查找流程定义开始节点
		YspDefNode yspDefNode = new YspDefNode().setDefId(yspDef.getId()).setType(YspDefNodeEnum.Type.START.value).queryFirst();
		
		// 添加任务审批记录
		YspTaskAudit yspTaskAudit = null;
		{
			Long taskId = yspTask.getId();
			Long prevId = 0L;
			Long nodeIdCurrent = yspDefNode.getId();
			Long nodeIdPrev = 0L;
			Integer state = YspTaskAuditEnum.State.FOR_AUDIT.value;
			String opinion = null;
			yspTaskAudit = YspTaskAudit.yspTaskAudit(taskId, prevId, nodeIdCurrent, nodeIdPrev, state, opinion, 1);
			yspTaskAuditMapper.insert(yspTaskAudit);
		}
		
		// 添加任务审批人
		YspTaskAuditUser yspTaskAuditUser = null;
		{
			Long taskId = yspTask.getId();
			Long taskAuditId = yspTaskAudit.getId();
			String userId = createUserId;
			Integer state = YspTaskAuditUserEnum.State.FOR_AUDIT.value;
			String opinion = null;
			yspTaskAuditUser = YspTaskAuditUser.yspTaskAuditUser(taskId, taskAuditId, userId, state, opinion, 1);
			yspTaskAuditUserMapper.insert(yspTaskAuditUser);
		}
		
		// 添加流程实例
		YsProcInst ysProcInst = null;
		{
			Long defId = yspDef.getId();
			Long taskId = yspTask.getId();
			Integer stateFlow = YsProcInstEnum.StateFlow.INIT.value;
			Long currentAuditId = yspTaskAudit.getId();
			ysProcInst = YsProcInst.ysProcInst(defId, taskId, bid, stateFlow, createUserId, currentAuditId, 1);
			ysProcInstMapper.insert(ysProcInst);
		}
		return R.ok();
	}

	@Override
	@Transactional
	public Flow flowPass(String bid, String loginUserId) throws Exception {
		YsProcInst ysProcInst = new YsProcInst().setBid(bid).queryFirst();
		if (ysProcInst == null) {
			return Flow.error("数据不存在");
		} else if (ysProcInst.getStateFlow() != YsProcInstEnum.StateFlow.INIT.value && ysProcInst.getStateFlow() != YsProcInstEnum.StateFlow.PROCESS.value) {
			return Flow.error("非制单或审核状态，无法操作");
		} else if (ysProcInst.getStatus() == 0) {
			return Flow.error("单据已删除，无法操作");
		}
		
		Long taskId = ysProcInst.getTaskId();
		
		/*
		 * 流转过程
		 * 1、查找任务
		 * 2、找到当前流转的路径节点
		 * 3、找到流程定义的节点
		 * 4、根据节点找到连接线
		 * 5、根据连接线找到下一个节点
		 */
		YspTask yspTask = new YspTask().setId(taskId).queryFirst();
		if (yspTask == null) {
			logger.error("taskId---", ysProcInst.getTaskId());
			return Flow.error("任务不存在");
		}
		
		// 当前节点审核数据
		YspTaskAudit yspTaskAuditCurrent = new YspTaskAudit().setId(ysProcInst.getCurrentAuditId()).queryFirst();
		if (yspTaskAuditCurrent.getState() != YspTaskAuditEnum.State.FOR_AUDIT.value) {
			logger.error("CurrentAuditId---", ysProcInst.getCurrentAuditId());
			return Flow.error("当前的审批状态有误");
		}
		// 判断是否需要当前用户处理
		Integer countYspTaskAuditUserCurrent = new YspTaskAuditUser()
				.setTaskAuditId(yspTaskAuditCurrent.getId())
				.setUserId(loginUserId)
				.setState(YspTaskAuditUserEnum.State.FOR_AUDIT.value)
				.count();
		if (countYspTaskAuditUserCurrent == 0) {
			return Flow.error("当前的审核人不是您，无法流转");
		}
		
		/*
		 * 若节点审核方式为角色并签，且还有多个用户待审核，则只需要更新审核用户的状态即可
		 */
		// 当前节点审核用户数据
		List<YspTaskAuditUser> listYspTaskAuditUser = new YspTaskAuditUser().setTaskAuditId(yspTaskAuditCurrent.getId()).setState(YspTaskAuditUserEnum.State.FOR_AUDIT.value).queryList();
		// 当前节点
		YspDefNode yspDefNode = new YspDefNode().setId(yspTaskAuditCurrent.getNodeIdCurrent()).queryFirst();
		if (yspDefNode.getAuditorType() == YspDefNodeEnum.AuditorType.ROLE_AND.value && listYspTaskAuditUser.size() > 1) {
			for(YspTaskAuditUser yspTaskAuditUser : listYspTaskAuditUser) {
				if (yspTaskAuditUser.getUserId().equals(loginUserId)) {
					yspTaskAuditUser.setState(YspTaskAuditUserEnum.State.SUCCESS.value);
					yspTaskAuditUserMapper.update(yspTaskAuditUser);
					return Flow.ok(Flow.State.PROCESS.value);
				}
			}
		}

		// 确定最终的节点
		FinalNodeDto dto = findFinalNode(ysProcInst, yspTask, yspTaskAuditCurrent,loginUserId);
		YspDefNode nodeFinal = dto.getNode();

		/*
		 *  根据最终节点，操作流程状态
		 */
		// 更新当前节点审核数据
		yspTaskAuditCurrent
			.setState(YspTaskAuditEnum.State.SUCCESS.value)
			.setOpinion("同意");
		yspTaskAuditMapper.update(yspTaskAuditCurrent);
		
		/*
		 * 更新当前节点审核用户数据-审核人
		 * 更新当前节点审核用户数据-其它审核人
		 */
		flowMapper.updateYspTaskAuditUserWhenSuccess(yspTaskAuditCurrent.getId(), loginUserId);
		
		// 添加下个节点审核数据
		YspTaskAudit yspTaskAuditNext = null;
		if (nodeFinal.getType() == YspDefNodeEnum.Type.DEFAULT.value) {
			Long prevId = yspTaskAuditCurrent.getId();
			Long nodeIdCurrent = nodeFinal.getId();
			Long nodeIdPrev = yspTaskAuditCurrent.getNodeIdCurrent();
			Integer state = YspTaskAuditEnum.State.FOR_AUDIT.value;
			String opinion = null;
			yspTaskAuditNext = YspTaskAudit.yspTaskAudit(taskId, prevId, nodeIdCurrent, nodeIdPrev, state, opinion, 1);
			yspTaskAuditMapper.insert(yspTaskAuditNext);
			
			// 添加下个节点审核用户数据
			List<String> listUserIdNext = findAuditorOfNode(nodeFinal, loginUserId, ysProcInst.getBid());
			for(String userId : listUserIdNext) {
				Long taskAuditId = yspTaskAuditNext.getId();
				Integer state2 = YspTaskAuditUserEnum.State.FOR_AUDIT.value;
				String opinion2 = null;
				YspTaskAuditUser yspTaskAuditUser = YspTaskAuditUser.yspTaskAuditUser(taskId, taskAuditId, userId, state2, opinion2, 1);
				yspTaskAuditUserMapper.insert(yspTaskAuditUser);
			}
		} else if (nodeFinal.getType() == YspDefNodeEnum.Type.END.value) {
			Long prevId = yspTaskAuditCurrent.getId();
			Long nodeIdCurrent = nodeFinal.getId();
			Long nodeIdPrev = yspTaskAuditCurrent.getNodeIdCurrent();
			Integer state = YspTaskAuditEnum.State.SUCCESS.value;
			String opinion = "任务结束";
			yspTaskAuditNext = YspTaskAudit.yspTaskAudit(taskId, prevId, nodeIdCurrent, nodeIdPrev, state, opinion, 1);
			yspTaskAuditMapper.insert(yspTaskAuditNext);
		}

		// 更新当前实例
		if (nodeFinal.getType() == YspDefNodeEnum.Type.DEFAULT.value) {
			ysProcInst
				.setStateFlow(YsProcInstEnum.StateFlow.PROCESS.value)
				.setCurrentAuditId(yspTaskAuditNext.getId());
			ysProcInstMapper.update(ysProcInst);
		} else if (nodeFinal.getType() == YspDefNodeEnum.Type.END.value) {
			ysProcInst
				.setStateFlow(YsProcInstEnum.StateFlow.FINISH.value);
			ysProcInstMapper.update(ysProcInst);
		}

		// 添加审核路径
		Long taskAuditId = yspTaskAuditNext.getId();
		Integer type = YspTaskFlowPathEnum.Type.PASS.value;
		addFlowPath(taskId, taskAuditId, type, dto.getPaths());
		
		// 返回数据
		if (nodeFinal.getType() == YspDefNodeEnum.Type.DEFAULT.value) {
			return Flow.ok(Flow.State.PROCESS.value);
		} else if (nodeFinal.getType() == YspDefNodeEnum.Type.END.value) {
			return Flow.ok(Flow.State.FINISH.value);
		} else {
			throw new RuntimeException("下个节点的类型有误，无法操作");
		}
	}


	//获取下一审批节点数据
	@Override
	public Map<String, Object> getNextTaskAuditUser(String loginUserId,String bid) throws Exception{
		boolean isError = false;
		String errorMsg = "";
		boolean isEnd = false;
		List<Map<String, Object>> userList = new ArrayList<>();
		Map<String, Object> res = new HashMap<>();

		YsProcInst ysProcInst = new YsProcInst().setBid(bid).queryFirst();
		if (ysProcInst == null) {
			res.put("isError",true);
			res.put("errorMsg","数据不存在");
			return res;
		}
		Long taskId = ysProcInst.getTaskId();
		YspTask yspTask = new YspTask().setId(taskId).queryFirst();
		if (yspTask == null) {
			res.put("isError",true);
			res.put("errorMsg","数据不存在");
			return res;
		}
		YspTaskAudit yspTaskAuditCurrent = new YspTaskAudit().setId(ysProcInst.getCurrentAuditId()).queryFirst();
		// 确定最终的节点
		FinalNodeDto dto = findFinalNode(ysProcInst, yspTask, yspTaskAuditCurrent,loginUserId);
		YspDefNode nodeFinal = dto.getNode();
		// 获取下个节点审核数据
		if (nodeFinal.getType() == YspDefNodeEnum.Type.DEFAULT.value) {

			// 获取下个节点审核用户数据
			List<String> listUserIdNext = findAuditorOfNode(nodeFinal, loginUserId, ysProcInst.getBid());
			for(String userId : listUserIdNext) {
				TsUserInfo userInfo = new TsUserInfo().setUserId(userId).queryFirst();
				if(userInfo!=null && userInfo.getId()!=null){
					Map<String, Object> info = new HashMap<>();
					info.put("userId",userId);
					info.put("userName",userInfo.getUserName());
					userList.add(info);
				}
			}
		} else if (nodeFinal.getType() == YspDefNodeEnum.Type.END.value) {
			isEnd = true;
		}
		res.put("isError",isError);
		res.put("errorMsg",errorMsg);
		res.put("isEnd",isEnd);
		res.put("userList",userList);
		return res;
	}



	@Override
	public FinalNodeDto findFinalNode(YsProcInst ysProcInst, YspTask yspTask, YspTaskAudit yspTaskAuditCurrent,String loginUserId) {

		boolean flag = true; // 结果标志，true有找到，false没有找到
		YspDefNode node = null; // 下一个节点
		List<FinalNodeDto.PathDto> paths = new ArrayList<FinalNodeDto.PathDto>(); // 经历的路径数组
		
		// 循环查找下一个节点，直到查找到普通节点和结束节点
		Long yspDefNodeIdCurrent = yspTaskAuditCurrent.getNodeIdCurrent();
		for(;;) {
			
			YspDefNode yspDefNodeCurrent = new YspDefNode().setId(yspDefNodeIdCurrent).queryFirst();
			if (yspDefNodeCurrent == null) {
				logger.error("nodeId---", yspTaskAuditCurrent.getNodeIdCurrent());
				return new FinalNodeDto(false, null, null);
			}
			NodeToDto nodeToDto = findNodeTo(ysProcInst, yspTask, yspDefNodeCurrent,loginUserId);
			// 找到的节点
			YspDefNode node2 = nodeToDto.getNode();
			
			// 把找到的节点添加到路径
			YspDefNode nodeFrom = yspDefNodeCurrent;
			YspDefNode nodeTo = nodeToDto.getNode();
			YspDefLink link = nodeToDto.getLink();
			paths.add(new FinalNodeDto.PathDto(nodeFrom, nodeTo, link));
			
			/*
			 *  找到非条件节点，则结束，并且在结束前把相关数据加入返回数据中
			 *  否则把找到的节点当做当前节点，继续查找下一个节点
			 */
			if (node2.getType() != YspDefNodeEnum.Type.CONDITIONAL.value) {
				
				node = node2;
				break;
			} else {
				
				// 把找到的节点当做当前节点，继续查找下一个节点
				yspDefNodeIdCurrent = nodeToDto.getNode().getId();
			}
		}
		FinalNodeDto dto = new FinalNodeDto(flag, node, paths);
		return dto;
	}

	@Override
	public NodeToDto findNodeTo(YsProcInst ysProcInst, YspTask yspTask, YspDefNode nodeCurrent,String loginUserId) {
		YspDefNode node = null;
		YspDefLink link = null;
		
		// 根据当前节点，处理下一个节点
		if (nodeCurrent.getType() == YspDefNodeEnum.Type.START.value || nodeCurrent.getType() == YspDefNodeEnum.Type.DEFAULT.value) {
			
			// 查找连接线
			link = new YspDefLink().setNodeIdFrom(nodeCurrent.getId()).setDefId(yspTask.getDefId()).queryFirst();
			// 根据连接线查找下一个节点
			node = new YspDefNode().setId(link.getNodeIdTo()).queryFirst();
			
		} else if (nodeCurrent.getType() == YspDefNodeEnum.Type.CONDITIONAL.value) {
			// 根据条件结果查找连接线
			JSONObject infoJO = JSON.parseObject(nodeCurrent.getInfo());
			String condition = infoJO.getString("cond");
			String bid = ysProcInst.getBid();
			//String loginUserId = ShiroUtils.getLoginUser().getUserId();
			Integer result = flowMapper.getResult(condition, bid, loginUserId);
			link = new YspDefLink().setNodeIdFrom(nodeCurrent.getId()).setCondResult(result).queryFirst();
			// 根据连接线查找下一个节点
			node = new YspDefNode().setId(link.getNodeIdTo()).queryFirst();
		} else {
			return null;
		}
		NodeToDto dto = new NodeToDto(node, link);
		return dto;
	}

	/**
	 * 查找审批人
	 * 返回审理人工号列表List
	 */
	@Override
	public List<String> findAuditorOfNode(YspDefNode node, String codeUserCurrent, String bid) throws Exception {
		Integer auditorType = node.getAuditorType();
		
		List<String> listUserId = new ArrayList<String>();
		
		if (auditorType == YspDefNodeEnum.AuditorType.DEPT_PARENT.value) {
			listUserId.add(flowMapper.getLeaderUserId(codeUserCurrent));
		} else if (auditorType == YspDefNodeEnum.AuditorType.OPERATOR_PARENT.value) {
			throw new RuntimeException("暂不支持运营机构上级类型审批");
		} else if (auditorType == YspDefNodeEnum.AuditorType.USER_POINTED.value) {
			listUserId.add(node.getAuditorValue());
		} else if (auditorType == YspDefNodeEnum.AuditorType.ROLE_AND.value || auditorType == YspDefNodeEnum.AuditorType.ROLE_OR.value) {
			String roleName = node.getAuditorValue();
			YsRole ysRole = new YsRole().setName(roleName).queryFirst();
			List<TsUserInfo> listTsUserInfo = new TsUserInfo().setRoleId(ysRole.getId()).queryList();
			for(TsUserInfo tsUserInfo : listTsUserInfo) {
				listUserId.add(tsUserInfo.getUserId());
			}
		} else if (auditorType == YspDefNodeEnum.AuditorType.CREATER.value) {
			YsProcInst ysProcInst = new YsProcInst().setBid(bid).queryFirst();
			listUserId.add(ysProcInst.getCreateUserId());
		}  else if (auditorType == YspDefNodeEnum.AuditorType.SCRIPT_POINT.value) {

			listUserId.add(flowMapper.getAuditUserId(node.getAuditorValue(),bid));
		} else {
			throw new RuntimeException("暂不支持其它类型审批");
		}
		
		// 固定每个节点审核添加admin
		if (!listUserId.contains("admin")) {
			listUserId.add("admin");
		}
		return listUserId;
	}

	@Override
	public R flowDelete(String bid, String loginUserId) throws Exception {
		YsProcInst ysProcInst = new YsProcInst().setBid(bid).queryFirst();
		if (ysProcInst == null) {
			return R.error("数据不存在");
		} else if (ysProcInst.getStateFlow() != YsProcInstEnum.StateFlow.INIT.value && ysProcInst.getStateFlow() != YsProcInstEnum.StateFlow.PROCESS.value) {
			return R.error("非制单状态，无法操作");
		} else if (ysProcInst.getStatus() == 0) {
			return R.error("单据已删除，无法操作");
		}
		
		ysProcInst.setStatus(0);
		ysProcInstMapper.update(ysProcInst);
		return R.ok();
	}

	@Override
	public R flowRefuse(String bid, String reason, String loginUserId) throws Exception {
		YsProcInst ysProcInst = new YsProcInst().setBid(bid).queryFirst();
		if (ysProcInst == null) {
			return R.error("数据不存在");
		} else if (ysProcInst.getStateFlow() != YsProcInstEnum.StateFlow.PROCESS.value) {
			return R.error("非审核状态，无法操作");
		}
		
		Long taskId = ysProcInst.getTaskId();
		
		/*
		 * 流转过程
		 * 1、查找任务审核
		 * 2、将当前任务审核置为失败
		 * 3、根据上一个任务添加审核任务
		 * 4、更新流程状态
		 */
		YspTask yspTask = new YspTask().setId(taskId).queryFirst();
		if (yspTask == null) {
			logger.error("taskId---", ysProcInst.getTaskId());
			return R.error("任务不存在");
		}
		
		// 当前节点审核数据
		YspTaskAudit yspTaskAuditCurrent = new YspTaskAudit().setId(ysProcInst.getCurrentAuditId()).queryFirst();
		if (yspTaskAuditCurrent.getState() != YspTaskAuditEnum.State.FOR_AUDIT.value) {
			logger.error("CurrentAuditId---", ysProcInst.getCurrentAuditId());
			return R.error("当前的审批状态有误");
		}
		YspTaskAuditUser yspTaskAuditUserCurrent = new YspTaskAuditUser()
				.setTaskAuditId(yspTaskAuditCurrent.getId())
				.setUserId(loginUserId)
				.queryFirst();
		if (yspTaskAuditUserCurrent == null) {
			return R.error("非当前任务审批人，无法操作");
		} else if (yspTaskAuditUserCurrent.getState() != YspTaskAuditUserEnum.State.FOR_AUDIT.value) {
			return R.error("当前的审批状态有误");
		}
		
		YspDefNode yspDefNodeCurrent = new YspDefNode().setId(yspTaskAuditCurrent.getNodeIdCurrent()).queryFirst();
		if (yspDefNodeCurrent == null) {
			logger.error("nodeId---", yspTaskAuditCurrent.getNodeIdCurrent());
			return R.error("流程定义节点不存在");
		} else if (yspDefNodeCurrent.getType() != YspDefNodeEnum.Type.DEFAULT.value) {
			logger.error("nodeId---", yspTaskAuditCurrent.getNodeIdCurrent());
			return R.error("非节点数据无法退回");
		}
		
		// 上一个审核数据
		YspTaskAudit yspTaskAuditPrev = new YspTaskAudit().setId(yspTaskAuditCurrent.getPrevId()).queryFirst();
		logger.error("prevId---", yspTaskAuditCurrent.getPrevId());
		if (yspTaskAuditPrev == null) {
			return R.error("未找到上一个审核数据，无法退回");
		}
		
		/*
		 * 更新当前节点审核用户数据-审核人
		 * 更新当前节点审核用户数据-其它审核人
		 */
		flowMapper.updateYspTaskAuditUserWhenFail(yspTaskAuditCurrent.getId(), loginUserId);
		
		// 更新当前审核数据
		yspTaskAuditCurrent
			.setState(YspTaskAuditEnum.State.FAILED.value)
			.setOpinion(reason);
		yspTaskAuditMapper.update(yspTaskAuditCurrent);
		
		// 添加审核数据
		YspTaskAudit yspTaskAuditAdd = null;
		{
			Long prevId = yspTaskAuditPrev.getPrevId();
			Long nodeIdCurrent = yspTaskAuditPrev.getNodeIdCurrent();
			Long nodeIdPrev = yspTaskAuditPrev.getNodeIdPrev();
			Integer state = YspTaskAuditEnum.State.FOR_AUDIT.value;
			String opinion = reason;
			yspTaskAuditAdd = YspTaskAudit.yspTaskAudit(taskId, prevId, nodeIdCurrent, nodeIdPrev, state, opinion, 1);
			yspTaskAuditMapper.insert(yspTaskAuditAdd);
		}
		
		// 添加上个节点审核用户数据
		List<YspTaskAuditUser> listYspTaskAuditUserPrev = new YspTaskAuditUser().setTaskAuditId(yspTaskAuditCurrent.getPrevId()).queryList();
		for(YspTaskAuditUser yspTaskAuditUser : listYspTaskAuditUserPrev) {
			Long taskAuditId = yspTaskAuditAdd.getId();
			String userId = yspTaskAuditUser.getUserId();
			Integer state2 = YspTaskAuditUserEnum.State.FOR_AUDIT.value;
			String opinion2 = null;
			YspTaskAuditUser entity = YspTaskAuditUser.yspTaskAuditUser(taskId, taskAuditId, userId, state2, opinion2, 1);
			yspTaskAuditUserMapper.insert(entity);
		}
		
		// 更新流程实例。若驳回到开始，则流程状态改为制单
		ysProcInst.setCurrentAuditId(yspTaskAuditAdd.getId());
		if (yspTaskAuditAdd.getPrevId().longValue() == 0L) {
			ysProcInst.setStateFlow(YsProcInstEnum.StateFlow.INIT.value);
		}
		ysProcInstMapper.update(ysProcInst);
		return R.ok();
	}

	@Override
	public R flowInit(String bid, String reason, String loginUserId) throws Exception {
		YsProcInst ysProcInst = new YsProcInst().setBid(bid).queryFirst();
		if (ysProcInst == null) {
			return R.error("数据不存在");
		} else if (ysProcInst.getStateFlow() != YsProcInstEnum.StateFlow.PROCESS.value) {
			return R.error("非审核状态，无法操作");
		}
		
		Long taskId = ysProcInst.getTaskId();
		
		/*
		 * 流转过程
		 * 1、查找任务审核
		 * 2、将当前任务审核置为失败
		 * 3、找到制单人，作为下一个任务的处理人
		 * 4、更新流程状态为初始状态
		 */
		YspTask yspTask = new YspTask().setId(taskId).queryFirst();
		if (yspTask == null) {
			logger.error("taskId---", ysProcInst.getTaskId());
			return R.error("任务不存在");
		}
		// 当前节点审核数据
		YspTaskAudit yspTaskAuditCurrent = new YspTaskAudit().setId(ysProcInst.getCurrentAuditId()).queryFirst();
		if (yspTaskAuditCurrent.getState() != YspTaskAuditEnum.State.FOR_AUDIT.value) {
			logger.error("CurrentAuditId---", ysProcInst.getCurrentAuditId());
			return R.error("当前的审批状态有误");
		}
		YspTaskAuditUser yspTaskAuditUserCurrent = new YspTaskAuditUser()
				.setTaskAuditId(yspTaskAuditCurrent.getId())
				.setUserId(loginUserId)
				.queryFirst();
		if (yspTaskAuditUserCurrent == null) {
			return R.error("非当前任务审批人，无法操作");
		} else if (yspTaskAuditUserCurrent.getState() != YspTaskAuditUserEnum.State.FOR_AUDIT.value) {
			return R.error("当前的审批状态有误");
		}
		
		YspDefNode yspDefNodeCurrent = new YspDefNode().setId(yspTaskAuditCurrent.getNodeIdCurrent()).queryFirst();
		if (yspDefNodeCurrent == null) {
			logger.error("nodeId---", yspTaskAuditCurrent.getNodeIdCurrent());
			return R.error("流程定义节点不存在");
		} else if (yspDefNodeCurrent.getType() != YspDefNodeEnum.Type.DEFAULT.value) {
			logger.error("nodeId---", yspTaskAuditCurrent.getNodeIdCurrent());
			return R.error("非节点数据无法退回");
		}
		
		/*
		 * 更新当前节点审核用户数据-审核人
		 * 更新当前节点审核用户数据-其它审核人
		 */
		flowMapper.updateYspTaskAuditUserWhenFail(yspTaskAuditCurrent.getId(), loginUserId);
		
		// 更新当前审核数据
		yspTaskAuditCurrent
			.setState(YspTaskAuditEnum.State.FAILED.value)
			.setOpinion(reason);
		yspTaskAuditMapper.update(yspTaskAuditCurrent);
		
		// 查找流程定义开始节点
		YspDefNode yspDefNode = new YspDefNode().setDefId(yspDefNodeCurrent.getDefId()).setType(YspDefNodeEnum.Type.START.value).queryFirst();
		
		// 添加任务审批记录
		YspTaskAudit yspTaskAudit = null;
		{
			Long prevId = 0L;
			Long nodeIdCurrent = yspDefNode.getId();
			Long nodeIdPrev = 0L;
			Integer state = YspTaskAuditEnum.State.FOR_AUDIT.value;
			String opinion = null;
			yspTaskAudit = YspTaskAudit.yspTaskAudit(taskId, prevId, nodeIdCurrent, nodeIdPrev, state, opinion, 1);
			yspTaskAuditMapper.insert(yspTaskAudit);
		}
		
		// 添加任务审批人
		YspTaskAuditUser yspTaskAuditUser = null;
		{
			Long taskAuditId = yspTaskAudit.getId();
			String userId = ysProcInst.getCreateUserId();
			Integer state = YspTaskAuditUserEnum.State.FOR_AUDIT.value;
			String opinion = null;
			yspTaskAuditUser = YspTaskAuditUser.yspTaskAuditUser(taskId, taskAuditId, userId, state, opinion, 1);
			yspTaskAuditUserMapper.insert(yspTaskAuditUser);
		}
		
		// 更新流程实例为制单
		ysProcInst.setCurrentAuditId(yspTaskAudit.getId());
		ysProcInst.setStateFlow(YsProcInstEnum.StateFlow.INIT.value);
		ysProcInstMapper.update(ysProcInst);
		return R.ok();
	
	}

	@Override
	public void addFlowPath(Long taskId, Long taskAuditId, Integer type, List<FinalNodeDto.PathDto> paths) {
		for (int i = 0; i < paths.size(); i++) {
			FinalNodeDto.PathDto path = paths.get(i);
			Long nodeIdFrom = path.getNodeFrom().getId();
			Long nodeIdTo = path.getNodeTo().getId();
			Long linkId = path.getLink().getId();
			Integer sortNo = i + 1;
			YspTaskFlowPath yspTaskFlowPath = YspTaskFlowPath.yspTaskFlowPath(
					taskId, taskAuditId, type, nodeIdFrom, nodeIdTo, linkId, sortNo, 1);
			yspTaskFlowPathMapper.insert(yspTaskFlowPath);
		}
	}

	@Override
	public Integer flowState(String bid) {
		YsProcInst entity = new YsProcInst().setBid(bid).queryFirst();
		if (entity == null) {
			return null;
		} else {
			return entity.getStateFlow();
		}
	}



	//修改审批流整单其他特殊参数信息
	@Override
	public R setOtherParams(String bid, Object remark, Object companyName) throws Exception {
		if(bid!=null && !"".equals(bid)){
			YsProcInstOther entity = new YsProcInstOther().setBid(bid).queryFirst();
			if(checkUtil.isNotNullByObject(remark) || checkUtil.isNotNullByObject(companyName)){
				if(entity!=null && entity.getId()!=null){
					entity.setBid(bid);
					entity.setStatus(1);
					if(checkUtil.isNotNullByObject(remark))entity.setRemark(remark.toString());
					if(checkUtil.isNotNullByObject(companyName))entity.setCompanyName(companyName.toString());
					ysProcInstOtherMapper.update(entity);
				}else {
					YsProcInstOther entityByNew = new YsProcInstOther()
							.setBid(bid)
							.setStatus(1);
					if(checkUtil.isNotNullByObject(remark))entityByNew.setRemark(remark.toString());
					if(checkUtil.isNotNullByObject(companyName))entityByNew.setCompanyName(companyName.toString());
					ysProcInstOtherMapper.insert(entityByNew);
				}
			}else {
				if(entity!=null && entity.getId()!=null){
					ysProcInstOtherMapper.deleteTrue(entity.getId());
				}
			}
		}
		return R.ok();
	}
}
